//*****************************************************************************
//
//								KeyRemo.c
//
//*****************************************************************************
//
//

#include "Config.h"
#include "reg.h"
#include "typedefs.h"
#include "Printf.h"
#include "I2C.h"
#include "CPU.h"
#include "Global.h"
#include "KeyRemo.h"

//EVB
#ifdef TW8823EVB
#define KEY_ADCMIN (0x100)
#define KEY_ADC1 (0x300)
#define KEY_ADC2 (0x500)
#define KEY_ADC3 (0x700)
#define KEY_ADC4 (0x900)
#define KEY_ADC5 (0xC00)
#define KEY_ADCMAX (0xE00)
#endif

//SH-DEMO
#ifdef TW8823SHDEMO
#define KEY_ADCMIN (0x0A0)
#define KEY_ADC1 (0x100)
#define KEY_ADC2 (0x200)
#define KEY_ADC3 (0x300)
#define KEY_ADC4 (0x3D0)
#define KEY_ADC5 (0x490)
#define KEY_ADC6 (0x550)
#define KEY_ADCMAX (0xFF0)
#endif




#define KEY_PRESS 0
#define KEY_POPUP 1
#define KEY_HOLD 0xD
#define KEY_IDLE 0xE
#define KEY_CLOSED 0xF


WORD key_adc = 0;
BYTE KeyState = KEY_CLOSED;

WORD GetAUX( BYTE channel );
//=============================================================================
//		WORD	GetAUX( BYTE channel )
//=============================================================================
WORD	GetAUX( BYTE channel )
{
	WORD	ADC;

	WriteTW88( 0xff, REMO_PAGE );
	//WriteTW88( 0x14, 0x03 );						// clock sel div16
	WriteTW88( 0x10, 0x0c + channel );				// write Start, erase Ready,
	//delay(1);
	WriteTW88( 0x10, 0x24 + channel );				// write Start, erase Ready,
	while (( ReadTW88( 0x10 ) & 8 ) != 8 ) ;
	ADC = ( ReadTW88( 0x12 ) << 4 ) + ReadTW88( 0x13 ) ;
	return ( ADC );
}

//=============================================================================
//		InitKey
//=============================================================================
void InitKey(void)
{
	key_adc = 0;
	KeyState = KEY_IDLE;
}
//=============================================================================
//		IntKey
//=============================================================================
BYTE IntKey(void)
{
	switch (KeyState){
		case KEY_POPUP:
		case KEY_IDLE:
			key_adc = GetAUX(0);
			if((key_adc >= KEY_ADCMIN)&&(key_adc < KEY_ADCMAX)){
				KeyState = KEY_PRESS;
				return 2;
			}else{
				KeyState = KEY_IDLE;
				return 0;
			}
			break;
		
		case KEY_PRESS:
		case KEY_HOLD:
			return 2;
			break;
		
		case KEY_CLOSED:
		default:
			return 0;
			break;
		
	}

}

//=============================================================================
//		ReadKey
//=============================================================================
BYTE ReadKey(void) 
{
	WORD	i, j;
	BYTE	min, max;

	switch (KeyState){
		case KEY_POPUP:
		case KEY_IDLE:
			key_adc = 0;
			break;
		
		case KEY_PRESS:
		case KEY_HOLD:
			//Pre
			key_adc = GetAUX(0);
			if ( key_adc<10 ){
				key_adc = 0;
				KeyState = KEY_POPUP;
				return (0);
			}
			//Alcu
			min = key_adc; max = key_adc;
			for ( j=0; j<17; j++ ) {
				i = GetAUX( 0 );
				if ( i<10 ){
					key_adc = 0;
					KeyState = KEY_POPUP;
 					return (0);
				}
				key_adc += i;
				if ( i < min ) min = i;
				else if ( i > max ) max = i;
			}
			key_adc -= min;
			key_adc -= max;

			key_adc >>= 4;	// divide by 16

			//Printf("\r\nKeyIn ADC Value is: 0x%x", (WORD)key_adc );
			if((key_adc >= KEY_ADCMIN)&&(key_adc < KEY_ADCMAX)){
				KeyState = KEY_HOLD;
			}else{
				key_adc = 0;
				KeyState = KEY_POPUP;
			}
			break;
			
		case KEY_CLOSED:
		default:
			key_adc = 0;
			break;
	}

	//Translate
	//EVB
	#ifdef TW8823EVB
	if ( key_adc < KEY_ADCMIN ){
		return( KEY_NONE );
	}else if ( key_adc < KEY_ADC1 ){
	  	//Puts("\nRIGHT pressed!!!");
		return( KEY_RIGHT );
	}else if ( key_adc < KEY_ADC2 ){
	  	//Puts("\nUP pressed!!!");
		return( KEY_UP );
	}else if ( key_adc < KEY_ADC3 ){
	  	//Puts("\nMENU pressed!!!");
		return( KEY_MENU );
	}else if ( key_adc < KEY_ADC4 ){
	  	//Puts("\nDOWN pressed!!!");
		return( KEY_DOWN );
	}else if ( key_adc < KEY_ADC5 ){
	  	//Puts("\nLEFT pressed!!!");
		return( KEY_LEFT );
	}else if ( key_adc < KEY_ADCMAX ){
	  	//Puts("\nINPUT pressed!!!");
		return( KEY_INPUT );
	}else{
		return( KEY_NONE );
	}
	#endif

	//SH-DEMO
	#ifdef TW8823SHDEMO
	if ( key_adc < KEY_ADCMIN ){
		return( KEY_NONE );
	}else if ( key_adc < KEY_ADC1 ){
		return( KEY_INPUT );
	}else if ( key_adc < KEY_ADC2 ){
		return( KEY_MENU );
	}else if ( key_adc < KEY_ADC3 ){
		return( KEY_RIGHT );
	}else if ( key_adc < KEY_ADC4 ){
		return( KEY_DOWN );
	}else if ( key_adc < KEY_ADC5 ){
		return( KEY_UP );
	}else if ( key_adc < KEY_ADC6 ){
		return( KEY_LEFT );
	}else if ( key_adc < KEY_ADCMAX ){
		return( KEY_PWR );
	}else{
		return( KEY_NONE );
	}
	#endif
}


#define		REMO_CUSTOM			0

BYTE	REMOTE_buf[4];
bit		RM_get = 0;
//=============================================================================
//		InitIR
//=============================================================================
void InitIR(void)
{
	REMOTE_buf[0] = 0;
	REMOTE_buf[1] = 0;
	REMOTE_buf[2] = 0;
	REMOTE_buf[3] = 0;
	RM_get = 0;
	
	//----- Enable IR-Remo
	WriteTW88( 0xff, REMO_PAGE );			// change page for REMOCON
	WriteTW88( 0xa2, 1 );					// enable IR
}
//=============================================================================
//		IntIR
//=============================================================================
void IntIR(void)
{
	BYTE RemoFlag;

	WriteTW88( 0xff, REMO_PAGE );  		// set page to REMOCON
	RemoFlag = ReadTW88( 0xa3 );
	if ( RemoFlag == 1 ){	// HT type remocon
		REMOTE_buf[0] = ReadTW88( 0xa5 );
		REMOTE_buf[1] = 0;
		REMOTE_buf[2] = 0;
		REMOTE_buf[3] = ReadTW88( 0xa4 ); // remo system code
		RM_get = 1;
		//Printf("\r\n IntIR HT 0x%bx|%bx|%bx|%bx", REMOTE_buf[0], REMOTE_buf[1], REMOTE_buf[2], REMOTE_buf[3]);
	}else if ( RemoFlag != 0 ){ // NEC type
		REMOTE_buf[0] = ReadTW88( 0xa9 );
		REMOTE_buf[1] = ReadTW88( 0xa8 );
		REMOTE_buf[2] = ReadTW88( 0xa7 );
		REMOTE_buf[3] = ReadTW88( 0xa6 );
		//Printf("\r\n IntIR NEC 0x%bx|%bx|%bx|%bx", REMOTE_buf[0], REMOTE_buf[1], REMOTE_buf[2], REMOTE_buf[3]);
	}


	WriteTW88( 0xa3, 0xff );  		// clear interrupt flags
	return;
}

//=============================================================================
//		BYTE IsRemoDataReady(BYTE *DataCode, BYTE *AutoKey)
//=============================================================================
BYTE IsRemoDataReady(BYTE *DataCode, BYTE *AutoKey)
{
	BYTE	togglebit;
	static  BYTE LastToggle=0;
	static  BYTE AutoWait=0;

	BYTE _RemoSystemCode, _RemoDataCode;

	if( !RM_get ) return 0;
	RM_get = 0;

	_RemoDataCode = REMOTE_buf[0];
	_RemoSystemCode = REMOTE_buf[3];

	*AutoKey = 0;

	//Printf("\r\n(CheckRemo)R-S:%02bx, R-D:%02bx", _RemoSystemCode, _RemoDataCode);

	//if( (_RemoSystemCode & 0xc0) != 0xc0 ) return 0;
	if( (_RemoSystemCode & 0x1f) != REMO_CUSTOM ) return 0;

	togglebit = LastToggle;
	if( _RemoSystemCode & 0x20 ) LastToggle = 1;
	else LastToggle = 0;


	if( LastToggle != togglebit ) {			// new key
		AutoWait =  0;
	}
	else if( AutoWait>=4 ) {			// auto key
		AutoWait++;
		if( AutoWait>=6 ) { 
			AutoWait = 4;
			*AutoKey = 1;
		}
		else return 0;
	}
	else {									// wait auto key
		AutoWait++;
		return 0;
	}
	
	/*
	if( *AutoKey ) {
		Puts(" ---> AutoKey ");
	}
	else {
		Puts(" ---> New Key ");
	}
	*/

	*DataCode = _RemoDataCode;
	return 1;
}


